use gloo_console::log;
use web_sys::{HtmlInputElement, HtmlSelectElement, HtmlTextAreaElement};
use yew::{platform::spawn_local, prelude::*};
use yew_router::prelude::*;

use crate::{
  api::{
    crates::{api_crate_create, api_crate_update, Crate},
    rustaceans::Rustacean,
  },
  components::{
    alert::Alert, input::Input, select::Select, textarea::Textarea,
  },
  contexts::CurrentUserContext,
  Route,
};

#[derive(Properties, PartialEq)]
pub struct Props {
  pub a_crate: Option<Crate>,
  pub authors: Vec<Rustacean>,
}

#[function_component]
pub fn CrateForm(props: &Props) -> Html {
  let name_handle = use_state(|| {
    if let Some(c) = &props.a_crate {
      c.name.clone()
    } else {
      String::default()
    }
  });
  let code_handle = use_state(|| {
    if let Some(c) = &props.a_crate {
      c.code.clone()
    } else {
      String::default()
    }
  });
  let rustacean_id_handle = use_state(|| {
    if let Some(c) = &props.a_crate {
      c.rustacean_id.to_string()
    } else {
      String::default()
    }
  });
  let version_handle = use_state(|| {
    if let Some(c) = &props.a_crate {
      c.version.to_string()
    } else {
      String::default()
    }
  });
  let description_handle = use_state(|| {
    if let Some(c) = &props.a_crate {
      if let Some(desc) = c.description.clone() {
        return desc;
      }
    }
    String::default()
  });
  let name = (*name_handle).clone();
  let code = (*code_handle).clone();
  let rustacean_id = (*rustacean_id_handle).clone();
  let version = (*version_handle).clone();
  let description = (*description_handle).clone();

  let navigator = use_navigator().expect("Navigator not available");
  let current_user_ctx = use_context::<CurrentUserContext>()
    .expect("Current user context is missing");

  let error_message_hander = use_state(String::default);
  let error_message = (*error_message_hander).clone();

  let name_changed = {
    move |e: Event| {
      e.stop_propagation();
      let target = e.target_dyn_into::<HtmlInputElement>();
      if let Some(input) = target {
        name_handle.set(input.value());
      }
      log!("name_changed");
    }
  };
  let code_changed = {
    move |e: Event| {
      e.stop_propagation();
      let target = e.target_dyn_into::<HtmlInputElement>();
      if let Some(input) = target {
        code_handle.set(input.value());
      }
      log!("code_changed");
    }
  };
  let rustacean_id_changed = {
    move |e: Event| {
      e.stop_propagation();
      let target = e.target_dyn_into::<HtmlSelectElement>();
      if let Some(input) = target {
        rustacean_id_handle.set(input.value());
      }
      log!("rustacean_id_changed");
    }
  };
  let version_changed = {
    move |e: Event| {
      e.stop_propagation();
      let target = e.target_dyn_into::<HtmlInputElement>();
      if let Some(input) = target {
        version_handle.set(input.value());
      }
      log!("version_handle");
    }
  };
  let description_changed = {
    move |e: Event| {
      e.stop_propagation();
      let target = e.target_dyn_into::<HtmlTextAreaElement>();
      if let Some(input) = target {
        description_handle.set(input.value());
      }
      log!("description_changed");
    }
  };

  let c_name = name.clone();
  let c_code = code.clone();
  let c_rustacean_id = rustacean_id.clone();
  let c_a_crate = props.a_crate.clone();
  let c_version = version.clone();
  let c_description = description.clone();

  let options = props
    .authors
    .iter()
    .map(|r| {
      (
        AttrValue::from(r.id.to_string()),
        AttrValue::from(r.name.clone()),
      )
    })
    .collect::<Vec<(AttrValue, AttrValue)>>();

  let onsubmit = {
    move |e: SubmitEvent| {
      e.prevent_default();

      let c_username = c_name.clone();
      let c_code = c_code.clone();
      let c_version = c_version.clone();
      let c_description = c_description.clone();
      let c_a_crate = c_a_crate.clone();
      let c_rustacean_id = c_rustacean_id.clone();

      let c_navigator = navigator.clone();
      let c_current_user_ctx = current_user_ctx.clone();
      let c_error_message_hander = error_message_hander.clone();

      match c_rustacean_id.parse::<i32>() {
        Ok(r_id) => match &c_current_user_ctx.token {
          Some(token) => {
            let c_token = token.clone();

            spawn_local(async move {
              if let Some(c) = &c_a_crate {
                match api_crate_update(
                  &c_token,
                  c.id,
                  c_username,
                  c_code,
                  r_id,
                  c_version,
                  c_description,
                )
                .await
                {
                  Ok(_) => c_navigator.push(&Route::Crates),
                  Err(err) => c_error_message_hander.set(err.to_string()),
                }
              } else {
                match api_crate_create(
                  &c_token,
                  c_username,
                  c_code,
                  r_id,
                  c_version,
                  c_description,
                )
                .await
                {
                  Ok(_) => c_navigator.push(&Route::Crates),
                  Err(err) => c_error_message_hander.set(err.to_string()),
                };
              }
            });
          }
          None => error_message_hander
            .set("Session expired.Please login again.".to_string()),
        },
        Err(_) => {
          c_error_message_hander.set("Cannot parse rustacean ID".to_string())
        }
      }
    }
  };

  html! {
     <form {onsubmit}>
      if error_message.len() > 0 {
        <Alert message={error_message} alert_type="error"/>
      }
      <div>
        <Input
          name="name"
          label="Name"
          input_type="text"
          value={name}
          onchange={name_changed}
        />
      </div>

      <div>
        <Input
          name="code"
          label="Code"
          input_type="text"
          value={code}
          onchange={code_changed}
        />
      </div>

      <div>
        <Select
          name="author"
          label="Author"
          value={rustacean_id}
          onchange={rustacean_id_changed}
          options={options}
        />
      </div>

      <div>
      <Input
        name="version"
        label="Version"
        input_type="text"
        value={version}
        onchange={version_changed}
      />
    </div>

      <div>
        <Textarea
          name="description"
          label="Description"
          value={description}
          onchange={description_changed}
        />
      </div>

      <button type="submit">{"Save"}</button>
    </form>
  }
}
